﻿using Onshi.POS.Modelo.Entidades;
using Onshi.POS.AccesoDatos.Interfaces;
using Onshi.POS.AccesoDatos;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Onshi.POS.Modelo.Entidades.Tipos;

namespace Onshi.POS.Repositorios
{
    public class RepositorioClientes : RepositorioEntidad<Cliente, Int32, IServicioDatosClientes>
    {
        #region Constructores

        public RepositorioClientes()
            : base()
        {
        }

        #endregion

        #region Atributos

        private RepositorioTiposIvas repositorioTiposIvas = new RepositorioTiposIvas();
        private RepositorioRubrosClientes repositorioRubrosClientes = new RepositorioRubrosClientes();
        private RepositorioTiposTelefonos repositorioTiposTelefonos = new RepositorioTiposTelefonos();
        private RepositorioTiposDomicilios repositorioTiposDomicilios = new RepositorioTiposDomicilios();
        private RepositorioBarrios repositorioBarrios = new RepositorioBarrios();
        private RepositorioTiposFormasPagos repositorioTiposFormasPagos = new RepositorioTiposFormasPagos();
        private RepositorioVendedores repositorioVendedores = new RepositorioVendedores();
        private RepositorioListasPreciosVentas repositorioListasPreciosVentas = new RepositorioListasPreciosVentas();
        private RepositorioCamposPersonalizadosClientes repositorioCamposPersonalizadosClientes = new RepositorioCamposPersonalizadosClientes();

        #endregion

        #region Metodos

        public override Cliente DevolverPorId(Int32 id)
        {
            return DevolverPorId(id, false);
        }

        public Cliente DevolverPorCodigo(String codigo)
        {
            return DevolverPorCodigo(codigo, false);
        }

        public List<Cliente> DevolverTodos()
        {
            return DevolverTodos(false);
        }

        public Cliente DevolverPorId(Int32 id, Boolean incluirImagen)
        {
            var cliente = entidades.Where(x => x.Id == id).FirstOrDefault();
            if (cliente == null)
                using (var ds = servicioDatos.Clientes_DevolverPorId(id, incluirImagen))
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        cliente = FilaAEntidad(ds.Tables[0].Rows[0]);
                        cliente.TiposFormasPagos = TablaAListaTiposFormasPagos(ds.Tables[1]);
                        cliente.Domicilios = TablaAListaDomicilios(ds.Tables[2]);
                        cliente.Telefonos = TablaAListaTelefonos(ds.Tables[3]);
                        cliente.CamposPersonalizados = TablaAListaCamposPersonalizados(ds.Tables[4]);
                        entidades.Add(cliente);
                    }
            return cliente;
        }

        public Cliente DevolverPorCodigo(String codigo, Boolean incluirImagen)
        {
            var cliente = entidades.Where(x => x.Codigo == codigo).FirstOrDefault();
            if (cliente == null)
                using (var ds = servicioDatos.Clientes_DevolverPorCodigo(codigo, incluirImagen))
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        cliente = FilaAEntidad(ds.Tables[0].Rows[0]);
                        cliente.TiposFormasPagos = TablaAListaTiposFormasPagos(ds.Tables[1]);
                        cliente.Domicilios = TablaAListaDomicilios(ds.Tables[2]);
                        cliente.Telefonos = TablaAListaTelefonos(ds.Tables[3]);
                        cliente.CamposPersonalizados = TablaAListaCamposPersonalizados(ds.Tables[4]);
                        entidades.Add(cliente);
                    }
            return cliente;
        }

        public List<Cliente> DevolverTodos(Boolean incluirImagen)
        {
            using (var ds = servicioDatos.Clientes_DevolverTodos(incluirImagen))
            {
                entidades = TablaALista(ds.Tables[0]);
                foreach (var cliente in entidades)
                {
                    var tiposFormasPagos = ds.Tables[1].AsEnumerable().Where(x => (Int32)x["IdCliente"] == cliente.Id).AsDataView().ToTable();
                    cliente.TiposFormasPagos = TablaAListaTiposFormasPagos(tiposFormasPagos);
                    var domicilios = ds.Tables[2].AsEnumerable().Where(x => (Int32)x["IdCliente"] == cliente.Id).AsDataView().ToTable();
                    cliente.Domicilios = TablaAListaDomicilios(domicilios);
                    var telefonos = ds.Tables[3].AsEnumerable().Where(x => (Int32)x["IdCliente"] == cliente.Id).AsDataView().ToTable();
                    cliente.Telefonos = TablaAListaTelefonos(telefonos);
                    var camposPersonalizados = ds.Tables[4].AsEnumerable().Where(x => (Int32)x["IdCliente"] == cliente.Id).AsDataView().ToTable();
                    cliente.CamposPersonalizados = TablaAListaCamposPersonalizados(camposPersonalizados);
                }
            }
            return entidades;
        }

        private List<TipoFormaPago> TablaAListaTiposFormasPagos(DataTable tabla)
        {
            var tiposFormasPagos = new List<TipoFormaPago>();
            foreach (DataRow item in tabla.Rows)
                tiposFormasPagos.Add(repositorioTiposFormasPagos.DevolverPorId((Byte)item["IdTipoFormaPago"]));
            return tiposFormasPagos;
        }

        private List<DomicilioCliente> TablaAListaDomicilios(DataTable tabla)
        {
            var domicilios = new List<DomicilioCliente>();
            foreach (DataRow fila in tabla.Rows)
                domicilios.Add(FilaADomicilio(fila));
            return domicilios;
        }

        private List<TelefonoCliente> TablaAListaTelefonos(DataTable tabla)
        {
            var telefonos = new List<TelefonoCliente>();
            foreach (DataRow fila in tabla.Rows)
                telefonos.Add(FilaATelefono(fila));
            return telefonos;
        }

        private List<ClienteCampoPersonalizadoCliente> TablaAListaCamposPersonalizados(DataTable tabla)
        {
            var camposPersonalizadosClientes = repositorioCamposPersonalizadosClientes.DevolverTodos();
            var clientesCamposPersonalizadosClientes = new List<ClienteCampoPersonalizadoCliente>();
            foreach (DataRow fila in tabla.Rows)
                clientesCamposPersonalizadosClientes.Add(FilaACampoPersonalizado(fila));
            foreach (var item in camposPersonalizadosClientes)
                if (!clientesCamposPersonalizadosClientes.Exists(x => x.Entidad.Id == item.Id))
                    clientesCamposPersonalizadosClientes.Add(new ClienteCampoPersonalizadoCliente()
                    {
                        Entidad = item,
                        Valor = String.Empty
                    });
            return clientesCamposPersonalizadosClientes;
        }

        private DomicilioCliente FilaADomicilio(DataRow fila)
        {
            var domicilio = new DomicilioCliente();
            domicilio.Id = (Int32)fila["IdDomicilioCliente"];
            domicilio.Calle = (String)fila["Calle"];
            domicilio.Numero = (String)fila["Numero"];
            domicilio.Piso = (String)fila["Piso"];
            domicilio.Departamento = (String)fila["Departamento"];
            domicilio.Tipo = repositorioTiposDomicilios.DevolverPorId((Byte)fila["IdTipoDomicilio"]);
            domicilio.Barrio = repositorioBarrios.DevolverPorId((Int32)fila["IdBarrio"]);
            return domicilio;
        }

        private TelefonoCliente FilaATelefono(DataRow fila)
        {
            var telefono = new TelefonoCliente();
            telefono.Id = (Int32)fila["IdTelefonoCliente"];
            telefono.CodigoArea = (String)fila["CodigoArea"];
            telefono.Numero = (String)fila["Numero"];
            telefono.Tipo = repositorioTiposTelefonos.DevolverPorId((Byte)fila["IdTipoTelefono"]);
            return telefono;
        }

        private ClienteCampoPersonalizadoCliente FilaACampoPersonalizado(DataRow fila)
        {
            var campoPersonalizado = new ClienteCampoPersonalizadoCliente();
            campoPersonalizado.Valor = (String)fila["Valor"];
            campoPersonalizado.Entidad = repositorioCamposPersonalizadosClientes.DevolverPorId((Int32)fila["IdCampoPersonalizadoCliente"]);
            return campoPersonalizado;
        }

        public void Insertar(Cliente cliente)
        {
            cliente.Id = servicioDatos.Clientes_Insertar(cliente.Rubro.Id, cliente.TipoIva.Id, cliente.ListaPrecioVenta.Id, cliente.Vendedor.Id, cliente.Codigo, cliente.Nombre, cliente.LimiteDeuda, cliente.Cuit, cliente.Email, cliente.SitioWeb, cliente.Observaciones, cliente.Imagen);
        }

        public void Modificar(Cliente cliente)
        {
            servicioDatos.Clientes_Modificar(cliente.Id, cliente.Rubro.Id, cliente.TipoIva.Id, cliente.ListaPrecioVenta.Id, cliente.Vendedor.Id, cliente.Codigo, cliente.Nombre, cliente.LimiteDeuda, cliente.Cuit, cliente.Email, cliente.SitioWeb, cliente.Observaciones, cliente.Imagen, cliente.EstaEliminado);
        }

        public void InsertarDomicilio(Cliente cliente, DomicilioCliente domicilio)
        {
            domicilio.Id = servicioDatos.DomiciliosClientes_Insertar(cliente.Id, domicilio.Tipo.Id, domicilio.Barrio.Id, domicilio.Calle, domicilio.Numero, domicilio.Piso, domicilio.Departamento);
        }

        public void EliminarDomiciliosPorCliente(Cliente cliente)
        {
            servicioDatos.DomiciliosClientes_EliminarPorCliente(cliente.Id);
        }

        public void InsertarTelefono(Cliente cliente, TelefonoCliente telefono)
        {
            telefono.Id = servicioDatos.TelefonosClientes_Insertar(cliente.Id, telefono.Tipo.Id, telefono.CodigoArea, telefono.Numero);
        }

        public void EliminarTelefonosPorCliente(Cliente cliente)
        {
            servicioDatos.TelefonosClientes_EliminarPorCliente(cliente.Id);
        }

        public void EliminarTiposFormasPagosPorCliente(Cliente cliente)
        {
            servicioDatos.ClientesTiposFormasPagos_EliminarPorCliente(cliente.Id);
        }

        public void InsertarTipoFormaPago(Cliente cliente, TipoFormaPago tipoFormaPago)
        {
            servicioDatos.ClientesTiposFormasPagos_Insertar(cliente.Id, tipoFormaPago.Id);
        }

        public void EliminarCamposPersonalizadosPorCliente(Cliente cliente)
        {
            servicioDatos.ClientesCamposPersonalizadosClientes_EliminarPorCliente(cliente.Id);
        }

        public void InsertarCampoPersonalizado(Cliente cliente, ClienteCampoPersonalizadoCliente campoPersonalizado)
        {
            servicioDatos.ClientesCamposPersonalizadosClientes_Insertar(cliente.Id, campoPersonalizado.Entidad.Id, campoPersonalizado.Valor);
        }

        protected override Cliente FilaAEntidad(DataRow fila)
        {
            var cliente = new Cliente();
            cliente.Id = (Int32)fila["IdCliente"];
            cliente.Codigo = (String)fila["Codigo"];
            cliente.Nombre = (String)fila["Nombre"];
            cliente.LimiteDeuda = (Decimal)fila["LimiteDeuda"];
            cliente.Cuit = (String)fila["Cuit"];
            cliente.Email = (String)fila["Email"];
            cliente.SitioWeb = (String)fila["SitioWeb"];
            cliente.Observaciones = (String)fila["Observaciones"];
            if (fila["Imagen"] != DBNull.Value)
                cliente.Imagen = (Byte[])fila["Imagen"];
            cliente.EstaEliminado = (Boolean)fila["EstaEliminado"];
            cliente.TipoIva = repositorioTiposIvas.DevolverPorId((Byte)fila["IdTipoIva"]);
            cliente.Rubro = repositorioRubrosClientes.DevolverPorId((Int32)fila["IdRubroCliente"]);
            cliente.ListaPrecioVenta = repositorioListasPreciosVentas.DevolverPorId((Int32)fila["IdListaPrecioVenta"]);
            cliente.Vendedor = repositorioVendedores.DevolverPorId((Int32)fila["IdVendedor"]);
            return cliente;
        }

        public void EliminarCamposPersonalizadosPorCampoPersonalizado(CampoPersonalizadoCliente campoPersonalizadoCliente)
        {
            servicioDatos.ClientesCamposPersonalizadosClientes_EliminarPorCampoPersonalizadoCliente(campoPersonalizadoCliente.Id);
        }

        public void ModificarBarrioEnDomicilios(Barrio barrioNuevo, Barrio barrioViejo)
        {
            servicioDatos.DomiciliosClientes_ModificarBarrio(barrioNuevo.Id, barrioViejo.Id);
        }

        public void ModificarRubroCliente(RubroCliente rubroNuevo, RubroCliente rubroViejo)
        {
            servicioDatos.Clientes_ModificarRubroCliente(rubroNuevo.Id, rubroViejo.Id);
        }

        public void ModificarVendedor(Vendedor vendedorNuevo, Vendedor vendedorViejo)
        {
            servicioDatos.Clientes_ModificarVendedor(vendedorNuevo.Id, vendedorViejo.Id);
        }

        #endregion
    }
}
